package com.katze.boot.file.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.katze.boot.file.dao.FolderMapper;
import com.katze.boot.file.entity.FileDatabaseEntity;
import com.katze.boot.file.entity.FolderEntity;
import com.katze.boot.file.service.FolderService;
import com.katze.common.Pagination;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.Optional;
import java.util.function.Function;


/**
* 说  明： 服务类
* 作  者：admin
* 日  期：2023-12-07
*/
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class FolderServiceImpl extends ServiceImpl<FolderMapper, FolderEntity> implements FolderService {
    private static final Logger log = LoggerFactory.getLogger(FolderServiceImpl.class);

    @Override
    public Object findFolders(Pagination pagination, FolderEntity folder) {
        try {
            QueryWrapper<FolderEntity> wrapper = Wrappers.query(FolderEntity.class)
                    .like(StringUtils.isNotBlank(folder.getName()), "f.name", folder.getName())
                    .eq(StringUtils.isNotBlank(folder.getFileDatabaseId()), "f.file_database_id", folder.getFileDatabaseId())
                    .orderByDesc("f.create_time");
            if (pagination.isEnabled()) {
                return this.page(pagination.toPage(), wrapper);
            } else {
                return this.list(wrapper);
            }
        } catch (Exception e) {
            log.error("获取目录记录失败", e);
            return null;
        }
    }

    @Override
    @Transactional
    public boolean create(FileDatabaseEntity fileDatabase, Function<FileDatabaseEntity, Boolean> update) throws IOException {
        // 先保留原始文件库信息，新目录创建失败后继续使用旧目录
        String preId = fileDatabase.getCurrentFolderId();
        String preName = fileDatabase.getCurrentFolderName();

        FolderEntity folder = new FolderEntity(fileDatabase.getId());
        // 创建新目录
        File target = new File(fileDatabase.getPath(), folder.getName());
        try {
            Files.createDirectories(target.toPath());
        } catch (IOException e) {
            log.error("{}下创建存储目录{}失败", fileDatabase.getPath(), folder.getName(), e);
            throw new IOException("目录创建失败");
        }
        try {
            save(folder);
            fileDatabase.setCurrentFolderId(folder.getId());
            fileDatabase.setCurrentFolderName(folder.getName());
            return update.apply(fileDatabase);
        } catch (Exception e) {
            log.error("当前文件库信息更新失败: {}", fileDatabase, e);
            fileDatabase.setCurrentFolderId(preId);
            fileDatabase.setCurrentFolderName(preName);
            throw new IOException("当前文件库信息更新失败");
        }
    }

    @Override
    public void delete(String id, boolean fileDatabase) {
        QueryWrapper<FolderEntity> wrapper = Wrappers.query(FolderEntity.class)
                .eq(!fileDatabase, "f.id", id).eq(fileDatabase, "f.file_database_id", id);
        File parent = null;
        // 删除存储目录和文件
        for (FolderEntity item : this.list(wrapper)) {
            File dir = new File(item.getPath(), item.getName());
            Optional.ofNullable(dir.listFiles()).map(Arrays::stream).ifPresent(stream -> stream.forEach(File::delete));
            dir.delete();
            baseMapper.deleteById(item.getId());
            if (fileDatabase && parent == null) parent = dir.getParentFile();
        }
        // 删除文件库目录
        if (parent != null) {
            parent.delete();
        }
    }
}
